package hu.mapro.gamelib;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Label.LabelStyle;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle;
import com.badlogic.gdx.scenes.scene2d.utils.Align;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;

public class SessionScreen implements Screen {
	
	final SessionFactory sessionFactory;
	Session currentSession;
	
	public SessionScreen(SessionFactory sessionFactory) {
		super();
		this.sessionFactory = sessionFactory;
		
		Gdx.input.setInputProcessor(inputs);
		initPauseMenu();
		
		debugCamera = new OrthographicCamera();
		debugBatch = new SpriteBatch();
		debugFont = new BitmapFont(true);
		
		shapeRenderer = new ShapeRenderer();
		
		startNewSession();
	}
	
	GameStatus gameStatus = GameStatus.PAUSED;

	public InputMultiplexer inputs = new InputMultiplexer();
	private Stage stage;

	final public OrthographicCamera debugCamera;
	final SpriteBatch debugBatch;
	final ShapeRenderer shapeRenderer;
	final BitmapFont debugFont;
	private Table menuTable;

	@Override
	final public void render(float delta) {

		switch (gameStatus) {
		case RUNNING:
			currentSession.update(delta);
			currentSession.draw();
			break;
		case PAUSED:
			stage.act(Gdx.graphics.getDeltaTime());
			currentSession.draw();
			drawPaused();
		}
		
		drawDebug();
	}

	public void drawDebug() {
		debugBatch.begin();
		debugBatch.setColor(Color.WHITE);
		debugFont.draw(debugBatch, "fps: " + Gdx.graphics.getFramesPerSecond(), 0, 0);
		
		float r = 50 * Gdx.graphics.getDensity();
		shapeRenderer.setProjectionMatrix(debugCamera.combined);
		shapeRenderer.begin(ShapeType.Line);
		shapeRenderer.setColor(Color.WHITE);
		shapeRenderer.circle(r, r, r);
		shapeRenderer.end();
		
		
		debugBatch.end();
	}

	protected void drawPaused() {
		stage.draw();
	}

	public class TimedTask implements Comparable<TimedTask> {

		final float scheduled;
		final Runnable runnable;

		public TimedTask(float scheduled, Runnable runnable) {
			super();
			this.scheduled = scheduled;
			this.runnable = runnable;
		}

		@Override
		public int compareTo(TimedTask o) {
			return Float.compare(scheduled, o.scheduled);
		}

	}

	public enum GameStatus {
		RUNNING, PAUSED,
	}

	protected void initPauseMenu() {
		stage = new Stage();

		menuTable = new Table();
		menuTable.setFillParent(true);
		stage.addActor(menuTable);

		float onePer160InchInPixels = Gdx.graphics.getDensity();
		float zeroPoint3InchInPixels = 0.4f * onePer160InchInPixels
				/ (1f / 160f);
		float targetHeight = zeroPoint3InchInPixels;

		LabelStyle titleStyle = new LabelStyle();
		titleStyle.font = new BitmapFont();
		titleStyle.font.setScale(targetHeight / titleStyle.font.getLineHeight()
				* 1.5f);
		titleStyle.fontColor = Color.BLUE;
		TextButtonStyle buttonStyle = new TextButtonStyle();
		buttonStyle.font = titleStyle.font;
		buttonStyle.font.setScale(targetHeight
				/ buttonStyle.font.getLineHeight());
		buttonStyle.fontColor = Color.WHITE;
		buttonStyle.overFontColor = Color.RED;

		Label title = new Label("Game Paused", titleStyle);
		title.setAlignment(Align.center);
		menuTable.add(title);
		menuTable.row();

		TextButton resumeButton = new TextButton("Resume", buttonStyle);
		menuTable.add(resumeButton);
		menuTable.row();

		TextButton restartButton = new TextButton("Restart", buttonStyle);
		menuTable.add(restartButton);
		menuTable.row();

		TextButton exitButton = new TextButton("Exit", buttonStyle);
		menuTable.add(exitButton);
		menuTable.row();

		resumeButton.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				super.clicked(event, x, y);
				menuResume();
			}
		});

		restartButton.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				super.clicked(event, x, y);
				menuRestart();
			}
		});

		exitButton.addListener(new ClickListener() {
			@Override
			public void clicked(InputEvent event, float x, float y) {
				super.clicked(event, x, y);
				menuExit();
			}
		});
		
	}

	protected void menuResume() {
		play();
	}
	
	public void runningRestart() {
		currentSession.pause();
		currentSession.dispose();
		createNewSession();
		currentSession.play();
	}

	public void menuRestart() {
		currentSession.dispose();
		startNewSession();
	}

	private void startNewSession() {
		createNewSession();
		play();
	}

	private void createNewSession() {
		currentSession = sessionFactory.createSession(this);
		currentSession.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
	}

	public void menuExit() {
		Gdx.app.exit();
	}

	@Override
	public void resize(int width, int height) {
		//float ratio = height / menuTable.getPrefHeight();
		float ratio = 3;
		stage.setViewport(width/ratio, height/ratio, false);
		
		debugCamera.setToOrtho(true);
		debugBatch.setProjectionMatrix(debugCamera.combined);
		
		currentSession.resize(width, height);
	}
	
	@Override
	public void pause() {
		currentSession.pause();
		gameStatus = GameStatus.PAUSED;
		inputs.addProcessor(stage);
	}

	public void play() {
		inputs.removeProcessor(stage);
		gameStatus = GameStatus.RUNNING;
		currentSession.play();
	}
	
	@Override
	public void resume() {
	}

	@Override
	public void hide() {
		shapeRenderer.dispose();
		stage.dispose();
		debugFont.dispose();
		debugBatch.dispose();
		Gdx.input.setInputProcessor(null);
	}

	@Override
	public void show() {
	}

	@Override
	public void dispose() {
	}
	
	

}
